package org.game.db.vo;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.base.BaseGoods;
import org.cache.GoodsCfgCache;
import org.cfg.ItemTimeCfg;
import org.constant.ItemType;
import org.game.db.bean.Item;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sojoys.artifact.tools.ToolDate;
import com.sojoys.artifact.tools.ToolMap;

/**
 * @author : DengYing
 * @CreateDate : 2017年10月13日 上午10:27:51
 * @Description ：玩家背包
 */
public class BackpackVO {
	
	/**
	 * CID 对应的单个道具
	 */
	private Map<Integer, Item> objcetForCid = Maps.newConcurrentMap();

	/**
	 * CID 对应的道具列表
	 */
	private Map<Integer, List<Item>> listForCid = Maps.newConcurrentMap();
	
	/**
	 * ID 映射
	 */
	private Map<Long, Item> itemForId = Maps.newConcurrentMap();
	
	
	/**
	 * cid 对应的实例个数映射
	 */
	private Map<Integer, Integer> countByCid = Maps.newHashMap();
	
	/**
	 * 拥有道具的子道具映射
	 */
	private Map<Integer, Set<String>> superCidMaping = Maps.newHashMap();
	
	/** 最大空间 */
	private int maxSpace = 0;
	
	public BackpackVO(int maxSpace) {
		super();
		this.maxSpace = maxSpace;
	}
	
	public void addItem(Item item){
		BaseGoods cfg = item.getItemProxy().getCfg();
		
		// CID 映射
		if (cfg.getPileUp()) {
			objcetForCid.put(item.getCid(), item);
		}else {
			List<Item> list = listForCid.get(item.getCid());
			if (list == null) {
				list = Lists.newArrayList();
				listForCid.put(item.getCid(), list);
			}
			list.add(item);
		}
		
		// ID 映射
		itemForId.put(item.getId(), item);
		
		
		int cid = item.getCid();
		// 做时限道具映射
		if (cfg instanceof ItemTimeCfg) {
			ItemTimeCfg itemTimeCfg = (ItemTimeCfg) cfg;
			Set<String> childIds = superCidMaping.get(itemTimeCfg.getItemId());
			if (childIds == null) {
				childIds = new TreeSet<>();
				superCidMaping.put(itemTimeCfg.getItemId(), childIds);
			}
			
			String key = getItemTimeOutItem(item)+"-"+itemTimeCfg.getId();
			childIds.add(key);
			
			cid = itemTimeCfg.getItemId();
		}
		
		// 根据CID合计道具数量
		Integer count = countByCid.get(cid);
		if (count == null) {
			count = item.getNum();
		}else {
			count+=item.getNum();
		}
		countByCid.put(item.getCid(), count);
	}
	
	public void removeGoods(Item item){
		BaseGoods cfg = item.getItemProxy().getCfg();
		if (cfg.getPileUp()) {
			objcetForCid.remove(item.getCid());
		}else {
			List<Item> list = listForCid.get(item.getCid());
			if (list != null) {
				list.remove(item);
				if (list.isEmpty()) {
					listForCid.remove(item.getCid());
				}
			}
		}
		
		
		int cid = item.getCid();
		if (cfg instanceof ItemTimeCfg) {
			ItemTimeCfg itemTimeCfg = (ItemTimeCfg) cfg;
			Set<String> childIds = superCidMaping.get(itemTimeCfg.getItemId());
			if (childIds != null) {
				String key = getItemTimeOutItem(item)+"-"+itemTimeCfg.getId();
				childIds.remove(key);
				
				if (childIds.isEmpty()) {
					superCidMaping.remove(itemTimeCfg.getItemId());
				}
			}
			cid = itemTimeCfg.getItemId();
		}
		
		Integer count = countByCid.get(cid);
		if (count != null) {
			count-=item.getNum();
			if (count < 1) {
				countByCid.remove(item.getCid());
			}else {
				countByCid.put(item.getCid(), count);				
			}
		}
	}
	
	/**
	 * 执行修改 & 并执行数据库操作
	 * @param item
	 * @param count
	 */
	public void changeCount(Item item,int count){
		BaseGoods cfg = item.getItemProxy().getCfg();
		int cid = item.getCid();
		
		if (cfg instanceof ItemTimeCfg) {
			ItemTimeCfg itemTimeCfg = (ItemTimeCfg) cfg;
			cid = itemTimeCfg.getItemId();
		}
		Integer num = countByCid.get(cid) + count;
		countByCid.put(item.getCid(), num);
		
		
		item.setNum(item.getNum() + count);
		
		if (item.getNum() > 0) {
			item.update();			
		}else {
			item.delete();
		}
	}
	
	
	
	
	
	
	public void clear(){
		objcetForCid.clear();
		listForCid.clear();
		itemForId.clear();
		countByCid.clear();
		superCidMaping.clear();
	}

	
	
	/**
	 * 取得子道具ID
	 * @param cid
	 * @return
	 */
	public Set<String> getChildIds(int cid){
		return superCidMaping.get(cid);
	}
	
	public long getItemTimeOutItem(Item item){
    	BaseGoods baseGoods = item.getItemProxy().getCfg();
    	long outTime = 0;
        if (baseGoods instanceof ItemTimeCfg) {
        	ItemTimeCfg itemTimeCfg = (ItemTimeCfg) baseGoods;
			switch (itemTimeCfg.getLimitType()) {
			case ItemType.DYNAMIC_TIME_LIMIT:
				outTime = item.getCreateDate().getTime() + ToolDate.TIME_SECOND * itemTimeCfg.getLimitData();
				break;
			case ItemType.FIXED_TIME_LIMIT:
				outTime = itemTimeCfg.getLimitData() * ToolDate.TIME_SECOND;
				break;
			}
		}
        return outTime;
    }
	
	
	
	
	
	
	/**
	 * 取得能够叠加的物品
	 * @param cid
	 * @return
	 */
	public Item getItem(int cid){
		return objcetForCid.get(cid);
	}
	
	public List<Item> getItemList(int cid){
		return listForCid.get(cid);
	}
	
	public Collection<Item> getAll(){
		return itemForId.values();
	}
	
	/**
	 * 根据ID取得具体某个道具
	 * @param cid
	 * @return
	 */
	public Item getItem(long id){
		return itemForId.get(id);
	}
	
	
	/**
	 * 取得某种道具数量
	 * @param cid
	 * @return
	 */
	public int countByCfg(BaseGoods cfg){
		int cid = cfg.getId();
		if (cfg instanceof ItemTimeCfg) {
			ItemTimeCfg itemTimeCfg = (ItemTimeCfg) cfg;
			cid = itemTimeCfg.getItemId();
		}
		return ToolMap.getInt(cid, countByCid ,0);
	}

	/**
	 * 取得某种道具数量
	 * @param cid
	 * @return
	 */
	public int countByCfg(int cid){
		BaseGoods cfg  = GoodsCfgCache.me().get(cid);
		return countByCfg(cfg);
	}
	
	/**
	 * 取得空闲容量
	 * @return
	 */
	public int getFreeCapacity(){
		return Math.max(0, (maxSpace - itemForId.size()));
	}
}
